How can I solve the same problems a CB-architecture is trying to solve without using hacks? [on hold]

Posted by Jefffrey on Game Development See other posts from Game Development or by Jefffrey
Published on 2013-10-22T15:36:25Z Indexed on 2013/10/22 16:04 UTC
Read the original article Hit count: 298

Filed under:
|
|

A component based system's goal is to solve the problems that derives from inheritance: for example the fact that some parts of the code (that are called components) are reused by very different classes that, hypothetically, would lie in a very different branch of the inheritance tree.

That's a very nice concept, but I've found out that CBS is often hard to accomplish without using ugly hacks. Implementations of this system are often far from clean. But I don't want to discuss this any further.

My question is: how can I solve the same problems a CBS try to solve with a very clean interface? (possibly with examples, there are a lot of abstract talks about the "perfect" design already).

Here's an example I was going for before realizing I was just reinventing inheritance again:

class Human {
public:
    Position position;
    Movement movement;
    Sprite   sprite;
    // other human specific components
};

class Zombie {
    Position position;
    Movement movement;
    Sprite   sprite;
    // other zombie specific components
};

After writing that I realized I needed an interface, otherwise I would have needed N containers for N different types of objects (or to use boost::variant to gather them all together). So I've thought of polymorphism (move what systems do in a CBS design into class specific functions):

class Entity {
public:
    virtual void on_event(Event) {} // not pure virtual on purpose
    virtual void on_update(World) {}
    virtual void on_draw(Window) {}
};

class Human {
private:
    Position position;
    Movement movement;
    Sprite   sprite;
public:
    virtual void on_event(Event) { ... }
    virtual void on_update(World) { ... }
    virtual void on_draw(Window) { ... }
};

class Zombie {
private:
    Position position;
    Movement movement;
    Sprite   sprite;
public:
    virtual void on_event(Event) { ... }
    virtual void on_update(World) { ... }
    virtual void on_draw(Window) { ... }
};

Which was nice, except for the fact that now the outside world would not even be able to know where a Human is positioned (it does not have access to its position member). That would be useful to track the player position for collision detection or if on_update the Zombie would want to track down its nearest human to move towards him.

So I added const Position& get_position() const; to both the Zombie and Human classes. And then I realized that both functionality were shared, so it should have gone to the common base class: Entity. Do you notice anything? Yes, with that methodology I would have a god Entity class full of common functionality (which is the thing I was trying to avoid in the first place).

© Game Development or respective owner

Related posts about c++

Related posts about game-design